package team.seekers.hula.island.post.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import team.seekers.hula.common.entity.PageResult;
import team.seekers.hula.common.entity.result.ApiExceptionEnum;
import team.seekers.hula.common.entity.enums.WindTypeEnum;
import team.seekers.hula.common.entity.result.ApiException;
import team.seekers.hula.common.utils.BaseConvertUtils;
import team.seekers.hula.island.island.service.IslandService;
import team.seekers.hula.island.islandUser.service.IslandUserService;
import team.seekers.hula.island.post.dao.IslandPostDao;
import team.seekers.hula.island.post.entity.dao.IslandPostDO;
import team.seekers.hula.island.post.entity.dto.IslandPostAddDTO;
import team.seekers.hula.island.post.entity.dto.IslandPostLinkDTO;
import team.seekers.hula.island.post.entity.dto.IslandPostQueryDTO;
import team.seekers.hula.island.post.entity.dto.IslandPostUpdateDTO;
import team.seekers.hula.island.post.entity.vo.IslandPostDateListVO;
import team.seekers.hula.island.post.entity.vo.IslandPostInfoVO;
import team.seekers.hula.island.post.entity.vo.IslandPostListVO;
import team.seekers.hula.island.postComment.entity.dto.PostCommentListDTO;
import team.seekers.hula.island.postComment.service.IslandPostCommentService;
import team.seekers.hula.message.message.service.MessageService;
import team.seekers.hula.record.wind.service.WindService;
import team.seekers.hula.auth.service.MindUtils;
import team.seekers.hula.user.user.service.UserService;
import team.seekers.hula.user.userFollow.service.UserFollowerService;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * @author ekin
 * @Description GOOD
 * @mood happy
 */
@Service
public class IslandPostService extends IslandPostDao{

    @Autowired
    private IslandPostDao islandPostDao;

    @Autowired
    private MessageService messageService;

    @Autowired
    private IslandUserService islandUserService;

    @Autowired
    private UserService userService;

    @Autowired
    private UserFollowerService userFollowerService;

    @Autowired
    private WindService windService;

    @Autowired
    private IslandService islandService;

    @Autowired
    private IslandPostCommentService islandPostCommentService;

    public String markOrDraft(IslandPostAddDTO post) {
        IslandPostDO islandPostDO = new IslandPostDO();
        islandPostDO.setType(islandService.getTypeById(post.getIslandId()));
        BeanUtils.copyProperties(post,islandPostDO);
        if(post.getPictures() != null && post.getPictures().size() > 0){
            islandPostDO.setPictures(BaseConvertUtils.listToString(post.getPictures()));
        }

        if(post.getLinks() != null){
            islandPostDO.setLinks(JSON.toJSONString(post.getLinks()));
        }

        if (post.getVisibility() == 2 && post.getType() == 0) {
            islandUserService.changeCount(post.getIslandId(),post.getUserId(),-1);
        }

        islandPostDao.saveOrUpdate(islandPostDO);

        if(post.getIsDraft() == 0){
            windService.addWind(WindTypeEnum.getByType(islandService.getTypeById(post.getIslandId())),islandPostDO.getId(),post.getVisibility());
        }

        return islandPostDO.getId();
    }

    public IslandPostUpdateDTO getEditInfo(String id) {
        IslandPostUpdateDTO islandPostUpdateDTO = new IslandPostUpdateDTO();
        IslandPostDO islandPostDO = islandPostDao.getById(id);
        BeanUtils.copyProperties(islandPostDO, islandPostUpdateDTO);
        islandPostUpdateDTO.setPictures(BaseConvertUtils.stringToList(islandPostDO.getPictures()));
        return islandPostUpdateDTO;
    }

    public void updatePost(IslandPostUpdateDTO updateDTO) {
        IslandPostDO islandPostDO = islandPostDao.getById(updateDTO.getId());
        BeanUtils.copyProperties(updateDTO, islandPostDO);
        islandPostDO.setPictures(BaseConvertUtils.listToString(updateDTO.getPictures()));
        islandPostDao.updateById(islandPostDO);
    }

//    public MessageInfoVO articleCommunication(IslandPostReplyDTO islandPostReplyDTO) {
//        IslandPostDO islandPostDO = islandPostDao.getById(islandPostReplyDTO.getIslandPostId());
//        IslandPostReplyVO islandPostReplyVO = new IslandPostReplyVO();
//        MessageInfoVO messageInfoVO = new MessageInfoVO();
//
//        MessageDO messageDO = new MessageDO();
//        messageDO.setFromId(MindUtils.getUserId());
//        messageDO.setToId(islandPostDO.getUserId());
////        messageDO.setType(NoticeTypeEnum.ADD_ANSWER_COMMENT);//TODO:具体消息类型
//        messageDO.setType(MessageTypeEnum.ANSWER_COMMENT);
//        messageDO.setDescription(islandPostReplyDTO.getReqReason());
//        messageDao.save(messageDO);
//
//        messageInfoVO.setContent(islandPostReplyDTO.getReqReason());
//        islandPostReplyVO.setName(islandPostDO.getTitle());
//        islandPostReplyVO.setContent(islandPostDO.getContent());
//        islandPostReplyVO.setToId(islandPostDO.getUserId());
//        messageInfoVO.setIslandPostReplyVO(islandPostReplyVO);
//
//        return messageInfoVO;
//    }

    public PageResult<IslandPostDateListVO> pageMemoryPost(IslandPostQueryDTO islandPostQueryDTO) {




        LambdaQueryWrapper<IslandPostDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(IslandPostDO::getIslandId, islandPostQueryDTO.getIslandId());


        if(islandPostQueryDTO.getVisibility() != null){
            switch (islandPostQueryDTO.getVisibility()){
                case 0:
                    wrapper.eq(IslandPostDO::getUserId, islandPostQueryDTO.getUserId());
                    break;
                case 1:
                    List<String> focusIds = userFollowerService.listAllFocusId(MindUtils.getUserId());
                    if(focusIds == null || focusIds.isEmpty()){
                        return new PageResult<>();
                    }
                    wrapper.in(IslandPostDO::getUserId, focusIds);
                    wrapper.eq(IslandPostDO::getVisibility, 1);
                    break;
                case 2:
                    wrapper.eq(IslandPostDO::getVisibility, 2);
                    break;
            }
        }

        wrapper.orderByDesc(IslandPostDO::getGmtCreate);

        // 获取最早时间
        Page<IslandPostDO> page = islandPostDao.page(new Page<>(islandPostQueryDTO.getPageNow(), islandPostQueryDTO.getPageSize()),wrapper);
        if(page.getTotal() == 0){
            return new PageResult<>();
        }

//        Date now = page.getRecords().get(0).getGmtCreate();
//        Calendar calendar = Calendar.getInstance();
//        calendar.setTime(now);
//
//        calendar.set(Calendar.SECOND, 0);
//        calendar.set(Calendar.MINUTE, 0);
//        calendar.set(Calendar.HOUR_OF_DAY, 0);
//        calendar.set(Calendar.MILLISECOND, 0);
//        Date zero = new Date(calendar.getTimeInMillis());
//        Date begin;
//        if(islandPostQueryDTO.getPageNow() == 1){
//            wrapper.ge(IslandPostDO::getGmtCreate,zero);
//            wrapper.le(IslandPostDO::getGmtCreate,now);
//            begin = zero;
//        }else{
//            calendar.add(Calendar.DAY_OF_MONTH,-islandPostQueryDTO.getPageNow()+1);
//            begin = new Date(calendar.getTimeInMillis());
//            calendar.add(Calendar.DAY_OF_MONTH,-islandPostQueryDTO.getPageNow()+2);
//            zero = new Date(calendar.getTimeInMillis());
//            wrapper.ge(IslandPostDO::getGmtCreate,begin);
//            wrapper.le(IslandPostDO::getGmtCreate,zero);
//        }
//        List<IslandPostDO> islandPostDOS = islandPostDao.list(wrapper);
//        if(islandPostDOS.size() == 0){
//            return new PageResult<>();
//        }

        ArrayList<IslandPostDateListVO> islandPostDateListVOS = new ArrayList<>();
        DateFormat dateFormat = new SimpleDateFormat("MM月dd日");
        for (IslandPostDO islandPostDO : page.getRecords()){
            IslandPostListVO islandPostListVO = new IslandPostListVO();
            BeanUtils.copyProperties(islandPostDO,islandPostListVO);
            islandPostListVO.setPictures(BaseConvertUtils.stringToList(islandPostDO.getPictures()));
            islandPostListVO.setUserInfo(userService.getFollowInfoVO(islandPostDO.getUserId(),MindUtils.getUserId()));
            islandPostListVO.setIsMine(MindUtils.getUserId().equals(islandPostDO.getUserId()));

            List<String> likeUserIds = BaseConvertUtils.stringToList(islandPostDO.getLikeUsers());
            islandPostListVO.setIsLike(likeUserIds != null && likeUserIds.contains(MindUtils.getUserId()));

            String date = dateFormat.format(islandPostDO.getGmtCreate());

            boolean isNew = true;
            for (IslandPostDateListVO islandPostDateListVO : islandPostDateListVOS) {
                if(islandPostDateListVO.getDate().equals(date)){
                    islandPostDateListVO.getPosts().add(islandPostListVO);
                    isNew = false;
                }
            }
            if(isNew){
                ArrayList<IslandPostListVO> islandPostListVOS = new ArrayList<>();
                islandPostListVOS.add(islandPostListVO);
                IslandPostDateListVO postDateListVO = IslandPostDateListVO.builder().date(date).posts(islandPostListVOS).build();
                islandPostDateListVOS.add(postDateListVO);
            }
        }

        Integer total = islandPostDao.lambdaQuery().eq(IslandPostDO::getIslandId, islandPostQueryDTO.getIslandId()).count();


        return new PageResult<>(total,islandPostDateListVOS);
    }

    public PageResult<IslandPostListVO> pagePost(IslandPostQueryDTO islandPostQueryDTO) {
        LambdaQueryChainWrapper<IslandPostDO> wrapper = islandPostDao.lambdaQuery();
        wrapper.eq(IslandPostDO::getIslandId, islandPostQueryDTO.getIslandId());

        if(islandPostQueryDTO.getVisibility() != null){
            switch (islandPostQueryDTO.getVisibility()){
                case 0:
                    wrapper.eq(IslandPostDO::getUserId, islandPostQueryDTO.getUserId());
                    break;
                case 1:
                    List<String> focusIds = userFollowerService.listAllFocusId(MindUtils.getUserId());
                    if(focusIds == null || focusIds.isEmpty()){
                        return new PageResult<>();
                    }
                    wrapper.in(IslandPostDO::getUserId, focusIds);
                    wrapper.eq(IslandPostDO::getVisibility, 1);
                    break;
                case 2:
                    wrapper.eq(IslandPostDO::getVisibility, 2);
                    break;
            }
        }

        if(islandPostQueryDTO.getVisibility() != null && islandPostQueryDTO.getVisibility() != 0){
            wrapper.eq(IslandPostDO::getVisibility, islandPostQueryDTO.getVisibility());
        }else if(islandPostQueryDTO.getVisibility() != null){

        }

        wrapper.orderByDesc(IslandPostDO::getGmtCreate);

        Page<IslandPostDO> page = wrapper.page(new Page<>(islandPostQueryDTO.getPageNow(), islandPostQueryDTO.getPageSize()));
        if(page.getRecords().size() == 0){
            return new PageResult<>();
        }

        List<IslandPostListVO> list = new ArrayList<>();
        for (IslandPostDO islandPostDO : page.getRecords()){
            IslandPostListVO islandPostListVO = new IslandPostListVO();
            BeanUtils.copyProperties(islandPostDO,islandPostListVO);

            islandPostListVO.setCommentCount(islandPostCommentService.countByPostId(islandPostDO.getId()));

            islandPostListVO.setPictures(BaseConvertUtils.stringToList(islandPostDO.getPictures()));
            islandPostListVO.setIsMine(MindUtils.getUserId().equals(islandPostDO.getUserId()));

            List<String> likeUserIds = BaseConvertUtils.stringToList(islandPostDO.getLikeUsers());
            islandPostListVO.setIsLike(likeUserIds != null && likeUserIds.contains(MindUtils.getUserId()));

            islandPostListVO.setUserInfo(userService.getFollowInfoVO(islandPostDO.getUserId(),MindUtils.getUserId()));

            if(islandPostDO.getVisibility() != 0){
                islandPostListVO.setComments(islandPostCommentService.getMyComment(PostCommentListDTO.builder().postId(islandPostDO.getId()).userId(MindUtils.getUserId()).build()));
            }
            list.add(islandPostListVO);
        }

        return new PageResult<>(page.getTotal(),list);
    }

    public IslandPostInfoVO info(String postId) {
        IslandPostDO postDO = islandPostDao.getById(postId);
        IslandPostInfoVO islandPostInfoVO = new IslandPostInfoVO();
        BeanUtils.copyProperties(postDO, islandPostInfoVO);

        islandPostInfoVO.setPictures(BaseConvertUtils.stringToList(postDO.getPictures()));

        if(postDO.getLinks() != null){
            islandPostInfoVO.setLinks(JSON.parseArray(postDO.getLinks(), IslandPostLinkDTO.class));
        }


        islandPostInfoVO.setUserInfo(userService.getFollowInfoVO(postDO.getUserId(),MindUtils.getUserId()));
        islandPostInfoVO.setIsMine(MindUtils.getUserId().equals(postDO.getUserId()));
        List<String> likeUserIds = BaseConvertUtils.stringToList(postDO.getLikeUsers());
        islandPostInfoVO.setIsLike(likeUserIds != null && likeUserIds.contains(MindUtils.getUserId()));
        return islandPostInfoVO;
    }

    public IslandPostUpdateDTO editPost(String islandId) {
        IslandPostDO one = islandPostDao
                .getOne(new QueryWrapper<IslandPostDO>()
                        .eq("user_id", MindUtils.getUserId())
                        .eq("is_draft", 1)
                        .eq("island_id", islandId));
        IslandPostUpdateDTO islandPostInfoVO = new IslandPostUpdateDTO();
        if (one == null) {
            return null;
        }
        BeanUtils.copyProperties(one, islandPostInfoVO);
        islandPostInfoVO.setPictures(BaseConvertUtils.stringToList(one.getPictures()));
        return islandPostInfoVO;
    }

    public void delete(String id) {
        // 判断是不是该用户的
        IslandPostDO islandPostDO = islandPostDao.
                lambdaQuery()
                .select(IslandPostDO::getUserId, IslandPostDO::getIslandId)
                .eq(IslandPostDO::getId, id).one();
        if(!MindUtils.getUserId().equals(islandPostDO.getUserId())){
            throw new ApiException(ApiExceptionEnum.USER_NO_PERMISSION);
        }

        // 删除
        islandPostDao.removeById(id);

        // 删除评论
        islandPostCommentService.removeByPostId(id);

        // 删除wind
        windService.removeWind(WindTypeEnum.getByType(islandService.getTypeById(islandPostDO.getIslandId())),id);
    }

    public void likeOrUnLike(String id) {
        String userId = MindUtils.getUserId();
        IslandPostDO islandPostDO = islandPostDao.lambdaQuery()
                .select(IslandPostDO::getLikeUsers, IslandPostDO::getLikeCount)
                .eq(IslandPostDO::getId, id)
                .one();
        String likeUsers = islandPostDO.getLikeUsers();
        Integer likeCount = islandPostDO.getLikeCount();
        List<String> likeUserIds = BaseConvertUtils.stringToList(likeUsers);
        if(likeUserIds == null){
            likeUserIds = new ArrayList<>();
            likeUserIds.add(userId);
            likeCount++;
        }else {
            if (likeUserIds.contains(userId)){
                likeUserIds.remove(userId);
                likeCount--;
            }else{
                likeUserIds.add(userId);
                likeCount++;
            }

        }
        islandPostDao.lambdaUpdate()
                .set(IslandPostDO::getLikeUsers,BaseConvertUtils.listToString(likeUserIds))
                .set(IslandPostDO::getLikeCount,likeCount)
                .eq(IslandPostDO::getId,id).update();

    }

    public Integer countByIslandId(String id) {
        return islandPostDao.lambdaQuery().eq(IslandPostDO::getIslandId,id).count();
    }

    public void addCommentCount(String postId) {
        IslandPostDO islandPostDO = lambdaQuery()
                .select(IslandPostDO::getId, IslandPostDO::getCommentCount)
                .eq(IslandPostDO::getId, postId).one();
        islandPostDO.setCommentCount(islandPostDO.getCommentCount()+1);
        islandPostDao.updateById(islandPostDO);
    }
}
